Catalyst 0.3.x provides Suspense support with SSR asset management powered by Vite. Legacy
Catalyst 0.2.x applications should continue using their @loadable/component integration until
they upgrade.
Installation
npm install [email protected] [email protected] [email protected]
Overview
Catalyst's Suspense implementation runs on Vite's build pipeline and provides:
- Smart Code Splitting: Automatic asset categorization (essential, SSR-enabled, SSR-disabled)
- Per-Component SSR Control: Fine-grained control over server-side rendering
- Intelligent Asset Loading: Essential assets load first, non-essential assets load progressively
- Streaming SSR: Non-blocking server-side rendering with progressive enhancement
- Automatic Asset Deduplication: Prevents loading duplicate resources
The split() Function
Use the split() function instead of React.lazy() for enhanced SSR compatibility and asset management:
Basic Usage
import { split } from "catalyst-core"// Basic split with SSR enabled (default)const LazyComponent = split(() => import("./LazyComponent"))// With custom fallbackconst LazyComponent = split(() => import("./LazyComponent"), {fallback: <div>Loading component...</div>})// Usage in componentconst Home = () => {return (<div><LazyComponent /></div>)}
SSR Control
Control whether components render on the server using the ssr flag:
// Component renders on server (default)const ServerRenderedComponent = split(() => import("./ServerComponent"), {ssr: true,fallback: <div>Loading...</div>})// Component only renders on clientconst ClientOnlyComponent = split(() => import("./ClientComponent"), {ssr: false,fallback: <div>Client-side only component loading...</div>})
Real-World Examples
Dashboard with Mixed SSR Strategy:
import { split } from "catalyst-core"// Critical above-the-fold content - SSR enabledconst DashboardHeader = split(() => import("./DashboardHeader"), {ssr: true,fallback: <div className="header-skeleton">Loading header...</div>})// Interactive widgets - client-side only for better performanceconst InteractiveChart = split(() => import("./InteractiveChart"), {ssr: false,fallback: <div className="chart-skeleton">Loading chart...</div>})// Settings modal - lazy load when neededconst SettingsModal = split(() => import("./SettingsModal"), {ssr: false,fallback: null // No fallback needed for modals})const Dashboard = () => {return (<div><DashboardHeader /><div className="content"><InteractiveChart />{/* SettingsModal loads only when state changes trigger it */}<SettingsModal /></div></div>)}
Asset Management
Catalyst automatically categorizes your assets based on how you use split():
Asset Categories
- Essential Assets: Core app functionality, entry points, shared utilities
- SSR-Enabled Assets: Components with
ssr: truethat load during server rendering - SSR-Disabled Assets: Components with
ssr: falsethat load only on the client
Loading Strategy
// This happens automatically:// 1. Essential assets load immediately// 2. SSR-enabled assets load during server rendering// 3. SSR-disabled assets load progressively on client
Migration from React.lazy
If you're upgrading from standard React.lazy, here's how to migrate:
Before (React.lazy)
import React, { Suspense, lazy } from "react"const LazyComponent = lazy(() => import("./LazyComponent"))const App = () => (<Suspense fallback={<div>Loading...</div>}><LazyComponent /></Suspense>)
After (Catalyst split)
import { split } from "catalyst-core"const LazyComponent = split(() => import("./LazyComponent"), {ssr: true, // or false based on your needsfallback: <div>Loading...</div>})const App = () => <LazyComponent />
Advanced Patterns
Conditional SSR Based on User Agent
const MobileOptimizedComponent = split(() => import("./MobileComponent"), {ssr: true,fallback: <div>Loading mobile view...</div>})const DesktopComponent = split(() => import("./DesktopComponent"), {ssr: true,fallback: <div>Loading desktop view...</div>})
Progressive Enhancement
// Base functionality loads with SSRconst BaseArticle = split(() => import("./BaseArticle"), {ssr: true,fallback: <div>Loading article...</div>})// Enhanced features load client-sideconst ArticleInteractions = split(() => import("./ArticleInteractions"), {ssr: false,fallback: null})const ArticlePage = () => (<div><BaseArticle /><ArticleInteractions /></div>)
Best Practices
1. SSR Strategy
- Enable SSR for above-the-fold content and SEO-critical components
- Disable SSR for highly interactive widgets, client-dependent features
- Use progressive enhancement by layering client-only features over SSR base content
2. Fallback Design
// Good: Meaningful loading statesconst Component = split(() => import("./Component"), {fallback: <div className="skeleton">Loading content...</div>})// Better: Match expected content structureconst Component = split(() => import("./Component"), {fallback: (<div className="article-skeleton"><div className="title-skeleton" /><div className="content-skeleton" /></div>)})
3. Performance Optimization
// Group related components to reduce chunk fragmentationconst UserProfile = split(() => import("./user/UserProfile"))const UserSettings = split(() => import("./user/UserSettings"))const UserActivity = split(() => import("./user/UserActivity"))
Troubleshooting
Components Not Loading on Server
If your component depends on clientFetcher data and fails on the server:
const DataDependentComponent = split(() => import("./DataComponent"), {ssr: false, // Disable SSR for client-data dependent componentsfallback: <div>Loading data-driven content...</div>})
Asset Loading Issues
The build system automatically handles asset categorization. If you experience issues:
- Check that imports use relative paths or configured aliases
- Ensure components are properly exported as default exports
Build System Integration
Catalyst's Suspense features integrate with Vite's build system:
- Manifest Categorization Plugin: Automatically categorizes assets during build
- Cache Key Injection Plugin: Optimizes asset tracking and loading
- ChunkExtractor: Intelligently manages asset dependencies during SSR
This integration ensures optimal performance without manual configuration.